"use strict";
function customScroll(){
	// cancel default browser events
	function cancelEvent(e){
		e = e ? e : window.event;
		if (e.stopPropagation){
			e.stopPropagation();
		}
		if (e.preventDefault) {
			e.preventDefault();
		}
		e.cancelBubble = true;
		e.cancel = true;
		e.returnValue = false;
		return false;
	}
	function whichButton(e) {
		if (!e.which && e.button) {
			e.which = e.button & 1 ? 1 : (e.button & 2 ? 3 : (e.button & 4 ? 2 : 0));
		}
		return e;
	}
	// custom scroll constructor
	function CustomScrollBar(parent,count) {
		var obj = this;
		this.buttonScrollSpeed = 40;
		this.parent = parent;
		//creating construction
		this.parent.innerHTML = '<div id="csb-' + count + '-innerWrapper" class="scrollable-block">' + this.parent.innerHTML + '</div>' +
		'<div id="csb-' + count + '-scrollBar" class="scrollbar">'+
			'<div id="csb-' + count + '-up" class="up"></div>'+
				'<div id="csb-' + count + '-scrollArea" class="scroll-area">'+
					'<div id="csb-' + count + '-scroller" class="scroller"><div class="t"></div><div class="b"></div></div>'+
				'</div>'+
			'<div id="csb-' + count + '-down" class="down"></div>' +
		'</div>';
		this.innerWrapper = document.getElementById('csb-' + count + '-innerWrapper');
		this.scrollBar = document.getElementById('csb-' + count + '-scrollBar');
		this.up = document.getElementById('csb-' + count + '-up');
		this.down = document.getElementById('csb-' + count + '-down');
		this.scrollArea = document.getElementById('csb-' + count + '-scrollArea');
		this.scroller = document.getElementById('csb-' + count + '-scroller');
		this.innerWrapper.style.marginTop = 0;
		this.parent.style.paddingRight = this.scrollBar.offsetWidth + 'px';
		
		// geometric size settings
		this.scrollArea.style.height = this.parent.offsetHeight - this.scrollBar.offsetHeight + 'px';
		this.scroller.style.display = 'block';
		
		// scroller resizing method
		this.scrollerResize = function(){
			this.scroller.style.height = this.scrollArea.offsetHeight*(this.parent.offsetHeight)/this.innerWrapper.offsetHeight + 'px';
		};
		this.scrollerResize();
		
		// show/hide scroller method
		this.scrollerShowHide = function(){
			if(this.innerWrapper.offsetHeight > this.parent.offsetHeight){
				this.scroller.style.display = 'block';
				this.hidden = false;
			} else{
				this.scroller.style.display = 'none';
				this.hidden = true;
				this.innerWrapper.style.marginTop = 0;
				this.scroller.style.top = 0;
			}
		};
		this.scrollerShowHide();
		
		//wheelScrollContent action
		this.wheelScrollContent = function(e){
			if (this.hidden === false) {
				e = e ? e : window.event;
				var wheelData = e.detail ? e.detail * 40 : e.wheelDelta * -1;
				if (parseFloat(this.innerWrapper.style.marginTop) - wheelData > 0) {
					this.innerWrapper.style.marginTop = 0;
					this.scroller.style.top = 0;
					if(!this.goingUpClosed){
						cancelEvent(e);
					}
					this.goingUpClosed = true;
					this.goingBottomClosed = false;
					return;
				} else if (parseFloat(this.innerWrapper.style.marginTop) - wheelData < this.parent.offsetHeight - this.innerWrapper.offsetHeight) {
					this.innerWrapper.style.marginTop = this.parent.offsetHeight - this.innerWrapper.offsetHeight + 'px';
					this.scroller.style.top = this.scrollArea.offsetHeight - this.scroller.offsetHeight + 'px';
					if(!this.goingBottomClosed){
						cancelEvent(e);
					}
					this.goingBottomClosed = true;
					this.goingUpClosed = false;
				} else {
					cancelEvent(e);
					this.innerWrapper.style.marginTop = parseFloat(this.innerWrapper.style.marginTop) - wheelData + 'px';
					this.scroller.style.top = -parseFloat(this.innerWrapper.style.marginTop) * 100 / this.innerWrapper.offsetHeight + '%';
					this.goingUpClosed = false;
					this.goingBottomClosed = false;
				}
			}
		};
		// scrolling by clicking at up/down arrows
		this.arrowsAction = function(dir,e){
			e = e || window.event;
			whichButton(e);
			if(e.which === 1){
				var shift = dir==='up' ? -this.buttonScrollSpeed : this.buttonScrollSpeed;
				this.innerWrapper.style.marginTop = parseInt(this.innerWrapper.style.marginTop,10) - shift + 'px';
				this.setPosition();
				setTimeout(function() {
					obj.scrollRepeat(shift);
				},300);
			}
		};
		this.scrollRepeat = function(shift){
			//this.inScrolling = true;
			var repeating = setInterval(function(){
				if(obj.inScrolling){
					obj.innerWrapper.style.marginTop = parseInt(obj.innerWrapper.style.marginTop,10) - shift/5 + 'px';
					obj.setPosition();
				} else{
					clearInterval(repeating);
				}
			},40);
		};
		// jump to point after click on scroll bar
		this.jumpToPoint = function(e){
			e = e || window.event;
			whichButton(e);
			if (e.which === 1) {
				var target = e.target || e.srcElement;
				var rect = target.getBoundingClientRect();
				var docElem = document.documentElement;
				var scrollTop = window.pageYOffset || docElem.scrollTop;
				var clientTop = docElem.clientTop || 0;
				var top = rect.top + scrollTop - clientTop;
				if (!e.pageY && e.clientY) {
					e.pageY = e.clientY + (document.documentElement.scrollTop || 0);
				}
				var shift = e.pageY - top;
				this.innerWrapper.style.marginTop = -this.innerWrapper.offsetHeight * shift / target.offsetHeight +
				this.parent.offsetHeight / 2 +
				'px';
				this.setPosition();
			}
		};
		// scrolling by scroller move
		this.scrollerMove = function(e){
			if(!e.pageY && e.clientY){
				e.pageY = e.clientY + (document.documentElement.scrollTop || 0);
			}
			var shift = e.pageY - obj.lastY;
			obj.innerWrapper.style.marginTop = parseInt(obj.innerWrapper.style.marginTop,10) - obj.innerWrapper.offsetHeight*shift/obj.scrollArea.offsetHeight + 'px';
			obj.setPosition();
			obj.lastY = e.pageY;
			cancelEvent(e);
		};
		// setting position of scrollable content and scroller
		this.setPosition = function(){
			if(this.innerWrapper.offsetHeight > this.parent.offsetHeight){
				if(parseFloat(this.innerWrapper.style.marginTop) > 0){
					this.innerWrapper.style.marginTop = 0;
					this.scroller.style.top = 0;
					return;
				} else if(parseFloat(this.innerWrapper.style.marginTop) < this.parent.offsetHeight - this.innerWrapper.offsetHeight){
					this.innerWrapper.style.marginTop = this.parent.offsetHeight - this.innerWrapper.offsetHeight + 'px';
					this.scroller.style.top = this.scrollArea.offsetHeight - this.scroller.offsetHeight + 'px';
				} else{
					this.scroller.style.top = - parseFloat(this.innerWrapper.style.marginTop)*100/this.innerWrapper.offsetHeight +'%';
				}
			}
			this.scrollerShowHide();
		};
		// handlers
		if (window.attachEvent){
			// scrolling by mousewheel
			this.parent.attachEvent('onmousewheel', function() {
				obj.wheelScrollContent(window.event);
			});
			
			this.parent.attachEvent('onmousedown', function() {
				function addScrollerMoving(){
					var e = window.event;
					obj.lastY = e.clientY + (document.documentElement.scrollTop || 0);
					if(e.button === 1){
						document.documentElement.attachEvent('onmousemove',obj.scrollerMove);
					}
					cancelEvent(e);
				}
				switch(window.event.srcElement) {
				// scrolling by clicking at DOWN arrows
				case obj.up:
					obj.inScrolling = true;
					obj.arrowsAction('up');
					break;
				// scrolling by clicking at UP arrows
				case obj.down:
					obj.inScrolling = true;
					obj.arrowsAction('down');
					break;
				// scrolling by clicking at scroll bar
				case obj.scrollArea:
					obj.jumpToPoint();
					break;
				// scrolling by moving at scroller
				case obj.scroller:
					addScrollerMoving();
					break;
				case obj.scroller.firstChild:
					addScrollerMoving();
					break;
				case obj.scroller.lastChild:
					addScrollerMoving();
					break;
				}
			});
			document.documentElement.attachEvent('onmouseup', function() {
				obj.inScrolling = false;
				document.documentElement.detachEvent('onmousemove',obj.scrollerMove);
			});
			window.attachEvent('onfocus', function() {
				obj.inScrolling = false;
				document.documentElement.detachEvent('onmousemove',obj.scrollerMove);
			});
			// document font resize handlers
			document.documentElement.attachEvent('onmousewheel', function() {
				setTimeout(function(){
					obj.scrollerResize();
					obj.setPosition();
				},0);
			});
		} else if (window.addEventListener){
			// scrolling by mousewheel
			this.parent.addEventListener('DOMMouseScroll', function(e) {
				obj.wheelScrollContent(e);
			}, false);
			this.parent.addEventListener('mousewheel', function(e) {
				obj.wheelScrollContent(e);
			}, false);
			this.parent.addEventListener('mousedown', function(e) {
				function addScrollerMoving(e){
					obj.lastY = e.pageY;
					if(e.which === 1){
						document.documentElement.addEventListener('mousemove',obj.scrollerMove,false);
					}
					cancelEvent(e);
				}
				switch(e.target) {
				// scrolling by clicking at UP arrows
				case obj.up:
					obj.inScrolling = true;
					obj.arrowsAction('up',e);
					break;
				// scrolling by clicking at DOWN arrows
				case obj.down:
					obj.inScrolling = true;
					obj.arrowsAction('down',e);
					break;
				// scrolling by clicking at scroll bar
				case obj.scrollArea:
					obj.jumpToPoint(e);
					break;
				// scrolling by moving at scroller
				case obj.scroller:
					addScrollerMoving(e);
					break;
				case obj.scroller.firstChild:
					addScrollerMoving(e);
					break;
				case obj.scroller.lastChild:
					addScrollerMoving(e);
					break;
				}
			}, false);
			window.addEventListener('mouseup', function() {
				obj.inScrolling = false;
				document.documentElement.removeEventListener('mousemove',obj.scrollerMove,false);
			},false);
			window.addEventListener('blur', function() {
				obj.inScrolling = false;
				document.documentElement.removeEventListener('mousemove',obj.scrollerMove,false);
			},false);
			// document font resize handlers
			window.addEventListener('DOMMouseScroll', function(event) {
				if (event.ctrlKey === true) {
					obj.scrollerResize();
					obj.setPosition();
				}
			}, false);
			window.addEventListener('keyup', function(event) {
				if (event.ctrlKey === true && event.which === 43||61||45||48||42) {
					obj.scrollerResize();
					obj.setPosition();
				}
			}, false);
			window.addEventListener('keydown', function(event) {
				if (event.ctrlKey === true && event.which === 43||61||45||48||42) {
					obj.scrollerResize();
					obj.setPosition();
				}
			}, false);
		}
	}
	
	// search of custom scroll blocks
	function init() {
		var DOM_tree = document.getElementsByTagName('*');
		var customObject = [];
		for (var i = 0; i < DOM_tree.length; i++){
			if(DOM_tree[i].className.indexOf('custom-scroll') != -1){
				customObject.push(DOM_tree[i]);
			}
		}
		for (var u = 0; u < customObject.length; u++) {
			customObject[u] = new CustomScrollBar(customObject[u],u);
		}
	}
	// init function
	if (window.attachEvent){
		window.attachEvent('onload', init);
		
	} else if (window.addEventListener){
		window.addEventListener('load', init, false);
	}
}

customScroll();